/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
*/

package com.jinhe.tss.core.cachepool.extend.assignment;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.log4j.Logger;

import com.jinhe.tss.core.cachepool.CacheManager;
import com.jinhe.tss.core.cachepool.extend.thread.IThreadPool;
import com.jinhe.tss.core.cachepool.strategy.CacheConstants;

/** 
 * <p> OutputRecordsManager.java </p> 
 * <br>输出记录类操作的管理类超类。 可输出日志、点击率、访问量等信息
 * <br>
 * <br>本超类中设置了一个存放记录的缓存，当缓存中的记录数到达最大值时，
 * <br>则会把缓存中的记录交给一个RecordsOutputTask任务，并调用工作线程池来执行该任务。
 * <br>
 * <br>本超类中同时还启用了一个守护的记录输出进程，当距离上次输出记录的时间达到最长等待时间时，
 * <br>则不管缓存是否已满只要有记录就都强制输出。
 * <br>
 * 
 * @author Jon.King 2007-2-15
 */
public abstract class OutputRecordsManager {
    protected Logger log = Logger.getLogger(this.getClass());
    
    private boolean isReady = true; //池是否已经初始化正确
    
    private final static int maxSize = 12;         //满12条就输出记录
    private final static int maxTime = 3*60*1000;  //定时输出记录的间隔时间：3分钟
    
    private List<Object> bufferedRecords = Collections.synchronizedList(new ArrayList<Object>());
    
    protected IThreadPool tpool;
    
    public OutputRecordsManager(){
        try{
            CacheManager manager = CacheManager.getInstance();
            tpool = (IThreadPool) manager.getCachePool(CacheConstants.THREAD_POOL);
        }catch(Exception e){
            isReady = false;
            log.error("初始化" + this.getClass() + "时初始化缓存池出错", e);
        }
        
        new FlushThread().start(); // 启动定时输出日志的收获线程
    }

    /**
     * 输出记录信息到缓存中，到临界值时输出缓存中记录到远程服务器端数据库中
     * @param dto
     */
    public synchronized void output(Object record){
        if(isReady) {
            bufferedRecords.add(record);
        }
        
        if(size() >= getMaxSize() ){  
            flush();   
        }    
    }   
    
    private int size(){ return bufferedRecords == null ? 0 : bufferedRecords.size(); }

    /**
     * 强制输出记录（为异步，调用线程池中的一个线程来完成）
     */
    public void flush(){      
        final List<Object> temp = bufferedRecords;
        reset();
        
        excuteTask(temp);
    }
    
    private void reset(){
        bufferedRecords = Collections.synchronizedList(new ArrayList<Object>());
    }
    
    /**
     * 执行输出记录（为异步，调用线程池中的一个线程来完成）
     * @param records
     */
    protected abstract void excuteTask(List<Object> records);
    
    
    protected int getMaxSize(){ return maxSize; }
    protected int getMaxTime(){ return maxTime;}
    
    /**
     * @author Jon.King  2007-2-15
     *
     * 记录定时输出，时间一满不管是否满了都输出去
     */
    private class FlushThread extends Thread{
        public void run() {
            while (true) {
                try {
                    sleep(getMaxTime()); /** 定期休眠，醒来后输出记录 */
                    if(size() > 0 ) {
                        flush();   
                    }
                } catch (InterruptedException e) {
                    log.error("运行OutputRecordsManager.FlushThread线程时出错！", e);
                }
            }
        }
    }
}